﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using AEM.Utils;

namespace AEM.Data.BLL.Actions
{
    public static class FaultLog
    {
        static FaultLog()
        {
            Add = doAdd;
            AddNC = doAddNC;
        }

        private static bool doAdd(SerialDataEventArgs e)
        {
            //string dir = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "datalogs", DateTime.Now.ToString("yyyyMMdd"));
            //if (!Directory.Exists(dir))
            //    Directory.CreateDirectory(dir);
            //string filename = Path.Combine(dir, e.LiftNum.ToString() + ".dll");

            //StringBuilder loginfo = new StringBuilder();
            //loginfo.Append(e.TimeRecieved.ToString("yyyy-MM-dd HH:mm:ss fff"));
            //loginfo.Append("=");
            //loginfo.Append(e.SerialDataRecieved.ToArray().toString<byte>());
            //loginfo.Append("|");

            //Byte[] info = new UTF8Encoding(true).GetBytes(loginfo.ToString());

            //FileStream fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);

            //BinaryWriter w = new BinaryWriter(fs);
            //fs.Position = fs.Length;
            //w.Write(info);

            //w.Close();
            //fs.Close();

            AddLog(e);

            return true;
        }

        private static bool AddLog(SerialDataEventArgs e)
        {
            string dir = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "datalogs", DateTime.Now.ToString("yyyyMMdd"));
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            string filename = Path.Combine(dir, e.LiftNum.ToString() + ".xml");

            Data.DataLog logdb = new Data.DataLog(filename);
            //累计运行次数、开关门次数
            AddUpCount(logdb, e.Run, e.Door);
            //记录电梯运行时间
            AddRunTime(logdb, e.LiftNum, e.Data.Rising, e.Data.Descending, e.TimeRecieved);
            
            //ADD NORMAL
            List<Data.DataLog.TableFaultLogRow> nlist = (from Data.DataLog.TableFaultLogRow i in logdb.TableFaultLog.Rows
                                                         where i.ET == i.ST && i.FT == (int)Enum.LiftStatus.Normal
                                                         select i).ToList();
            if (null == nlist || nlist.Count < 1)
                if (!(e.Data.Fire || e.Data.Overhaul || e.Data.OutOfService || e.Data.FaultLamp || e.Data.CageAlarm || e.Data.ConverterAlarm || e.Data.IsEarthquaked))
                {
                    addLog(e.LiftNum, e.TimeRecieved, Data.Enum.LiftStatus.Normal, logdb);
                }
            //ADD NORMAL END

            List<Data.DataLog.TableFaultLogRow> list = (from Data.DataLog.TableFaultLogRow i in logdb.TableFaultLog.Rows
                                                        where i.ET == i.ST
                                                        select i).ToList();
            foreach (var i in list)
            {
                switch ((Data.Enum.LiftStatus)i.FT)
                {
                    case Enum.LiftStatus.Fire:
                        if (!e.Data.Fire) i.ET = e.TimeRecieved;
                        else e.Data.Fire = false;
                        break;
                    case Enum.LiftStatus.Overhaul:
                        if (!e.Data.Overhaul) i.ET = e.TimeRecieved;
                        else e.Data.Overhaul = false;
                        break;
                    case Enum.LiftStatus.OutOfService:
                        if (!e.Data.OutOfService) i.ET = e.TimeRecieved;
                        else e.Data.OutOfService = false;
                        break;
                    case Enum.LiftStatus.Fault:
                        if (!e.Data.FaultLamp) i.ET = e.TimeRecieved;
                        else e.Data.FaultLamp = false;
                        break;
                    case Enum.LiftStatus.CageAlarm:
                        if (!e.Data.CageAlarm) i.ET = e.TimeRecieved;
                        else e.Data.CageAlarm = false;
                        break;
                    case Enum.LiftStatus.IsEarthquaked:
                        if (!e.Data.IsEarthquaked) i.ET = e.TimeRecieved;
                        else e.Data.IsEarthquaked = false;
                        break;
                    case Enum.LiftStatus.ConverterAlarm:
                        if (!e.Data.ConverterAlarm) i.ET = e.TimeRecieved;
                        else e.Data.ConverterAlarm = false;
                        break;
                    case Enum.LiftStatus.Normal:
                    default:
                        if (e.Data.Fire || e.Data.Overhaul || e.Data.OutOfService || e.Data.FaultLamp || e.Data.CageAlarm || e.Data.ConverterAlarm || e.Data.IsEarthquaked)
                        { i.ET = e.TimeRecieved; }
                        break;
                }
            }
            logdb.TableFaultLog.AcceptChanges();
            logdb.Save();

            if (e.Data.Fire) addLog(e.LiftNum, e.TimeRecieved, Data.Enum.LiftStatus.Fire, logdb);
            if (e.Data.Overhaul) addLog(e.LiftNum, e.TimeRecieved, Data.Enum.LiftStatus.Overhaul, logdb);
            if (e.Data.OutOfService) addLog(e.LiftNum, e.TimeRecieved, Data.Enum.LiftStatus.OutOfService, logdb);
            if (e.Data.FaultLamp) addLog(e.LiftNum, e.TimeRecieved, Data.Enum.LiftStatus.Fault, logdb);
            if (e.Data.CageAlarm) addLog(e.LiftNum, e.TimeRecieved, Data.Enum.LiftStatus.CageAlarm, logdb);
            if (e.Data.IsEarthquaked) addLog(e.LiftNum, e.TimeRecieved, Data.Enum.LiftStatus.IsEarthquaked, logdb);
            if (e.Data.ConverterAlarm) addLog(e.LiftNum, e.TimeRecieved, Data.Enum.LiftStatus.ConverterAlarm, logdb);

            if (e.Data.Fire || e.Data.Overhaul || e.Data.OutOfService || e.Data.FaultLamp || e.Data.CageAlarm || e.Data.ConverterAlarm || e.Data.IsEarthquaked)
                if (null != Actions.SerialPorts.SMSMonitoring)
                    Actions.SerialPorts.SMSMonitoring.BeginInvoke(e, new AsyncCallback(Actions.SerialPorts.SMSCallback), null);

            HallCallLog.Add.BeginInvoke(e, HallCallLog.AddCallback, null);
            return true;
        }

        private static void AddRunTime(DataLog logdb, int LiftNum, bool Rising, bool Descending, DateTime TimeRecieved)
        {
            Data.DataLog.TableRunTimeRow row = (from Data.DataLog.TableRunTimeRow i in logdb.TableRunTime.Rows
                                                where i.ST == i.ET
                                                orderby i.ST
                                                select i).FirstOrDefault();
            if (null != row)
            {
                if (!Rising && !Descending)
                {
                    row.ET = TimeRecieved;
                    row.AcceptChanges();
                    logdb.TableRunTime.AcceptChanges();
                    logdb.Save();
                }
            }
            else
            {
                if (Rising || Descending)
                {
                    Data.DataLog.TableRunTimeRow r = logdb.TableRunTime.NewTableRunTimeRow();
                    r.LN = LiftNum;
                    r.ST = r.ET = TimeRecieved;
                    logdb.TableRunTime.AddTableRunTimeRow(r);
                    logdb.TableRunTime.AcceptChanges();
                    logdb.Save();
                }
            }
        }

        /// <summary>
        /// //累计运行次数、开关门次数
        /// </summary>
        /// <param name="logdb"></param>
        /// <param name="run"></param>
        /// <param name="door"></param>
        private static void AddUpCount(DataLog logdb, int run, int door)
        {
            Data.DataLog.TableCountRow countRow = (from Data.DataLog.TableCountRow i in logdb.TableCount.Rows
                                                   select i).FirstOrDefault();
            if (null != countRow)
            {
                countRow.R = (countRow.R.toInt32() + run).ToString();
                countRow.D = (countRow.D.toInt32() + door).ToString();
            }
            else
            {
                Data.DataLog.TableCountRow r = logdb.TableCount.NewTableCountRow();
                r.R = run.ToString();
                r.D = door.ToString();
                logdb.TableCount.AddTableCountRow(r);
            }
            logdb.TableCount.AcceptChanges();
            logdb.Save();
        }

        private static int addLog(int liftnum, DateTime dt, Data.Enum.LiftStatus status, Data.DataLog logdb)
        {
            try
            {
                Data.DataLog.TableFaultLogRow row = logdb.TableFaultLog.NewTableFaultLogRow();
                row.LN = liftnum;
                row.FT = (int)status;
                row.ST = row.ET = dt;

                logdb.TableFaultLog.AddTableFaultLogRow(row);
                logdb.TableFaultLog.AcceptChanges();
                logdb.Save();
            }
            catch
            {
                //return false;
            }
            if (status != Enum.LiftStatus.Normal)
                if (null != Log.AddOperation)
                {
                    //string type = (string)System.Windows.Application.Current.TryFindResource(status.ToString());
                    string log = "=InfoNewFault," + liftnum + "," + status.ToString();// string.Format((string)System.Windows.Application.Current.TryFindResource("InfoNewFault"), liftnum, type);
                    Log.AddOperation.BeginInvoke(log, new AsyncCallback(Log.AddOperationCallback), null);
                }

            return 1;
        }

        private static bool doAddNC(int liftnum)
        {
            string dir = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "datalogs", DateTime.Now.ToString("yyyyMMdd"));
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            string filename = Path.Combine(dir, liftnum.ToString() + ".xml");
            Data.DataLog logdb = new Data.DataLog(filename);

            List<Data.DataLog.TableFaultLogRow> list = (from Data.DataLog.TableFaultLogRow i in logdb.TableFaultLog.Rows
                                                        where i.ET == i.ST && i.FT != (int)Data.Enum.LiftStatus.NC
                                                        select i).ToList();

            foreach (Data.DataLog.TableFaultLogRow row in list)
                row.ET = DateTime.Now;
            logdb.TableFaultLog.AcceptChanges();
            logdb.Save();

            Data.DataLog.TableFaultLogRow ncrow = (from Data.DataLog.TableFaultLogRow i in logdb.TableFaultLog.Rows
                                                   where i.ET == i.ST && i.FT == (int)Data.Enum.LiftStatus.NC
                                                   select i).FirstOrDefault();
            if (null == ncrow)
                addLog(liftnum, DateTime.Now, Enum.LiftStatus.NC, logdb);

            return true;
        }

        public static void AddNCCallback(IAsyncResult tag)
        {
            AsyncResult result = (AsyncResult)tag;
            Func<int, bool> del = (Func<int, bool>)result.AsyncDelegate;
            del.EndInvoke(tag);
        }

        public static void AddCallback(IAsyncResult tag)
        {
            AsyncResult result = (AsyncResult)tag;
            Func<SerialDataEventArgs, bool> del = (Func<SerialDataEventArgs, bool>)result.AsyncDelegate;
            del.EndInvoke(tag);
        }
        /// <summary>
        /// 添加数据接收记录
        /// </summary>
        public static Func<SerialDataEventArgs, bool> Add;

        public static Func<int, bool> AddNC;

    }
}
